package org.chaiyi.template.core.common.contract;

import lombok.SneakyThrows;
import org.chaiyi.template.core.common.exception.BaseErrorCode;
import org.chaiyi.template.core.common.repository.MongoEntity;
import org.chaiyi.template.core.common.supporter.MongoSupporter;
import org.chaiyi.template.core.common.util.asserts.Asserts;

/**
 * @author Gong.Yang
 */
public class ContractUtil {

    /**
     * 通过对象获取对应的契约接口
     */
    public static Class<?> getIService(Object bean) {
        Class<?> aClass = bean.getClass();
        return getIService(aClass);
    }

    /**
     * 获取当前实现类的契约接口
     */
    public static Class<?> getIService(Class<?> aClass) {
        String beanClassSimpleName = aClass.getSimpleName();
        Class<?>[] interfaces = aClass.getInterfaces();
        for (Class<?> anInterface : interfaces) {
            String interfaceSimpleName = anInterface.getSimpleName();
            if (!("I" + beanClassSimpleName).equals(interfaceSimpleName)) {
                continue;
            }
            return anInterface;
        }
        throw BaseErrorCode.CONTRACT_EXCEPTION.error();
    }


    /**
     * 获取契约接口中的契约信息接口
     */
    public static Class<?> getContract(Class<?> iService) {
        for (Class<?> declaredClass : iService.getDeclaredClasses()) {
            if (declaredClass.getSimpleName().equals("Contract")) {
                return declaredClass;
            }
        }
        throw BaseErrorCode.CONTRACT_EXCEPTION.error();
    }


    /**
     * 通过契约信息接口获取契约信息
     */
    @SneakyThrows
    private static ContractInfo getInfo(Class<?> contract, Class<?> iService) {


        String path = (String) contract.getDeclaredField("path").get(null);
        BaseErrorCode.CONTRACT_EXCEPTION.throwIf(Asserts.isBlank(path));
        path = "/api/{tenantId}/{buCode}/" + path;

        String name = (String) contract.getDeclaredField("name").get(null);

        Class<? extends MongoSupporter> supporter = (Class<? extends MongoSupporter>) contract.getDeclaredField("supporter").get(null);
        Class<? extends MongoEntity> entity = (Class<? extends MongoEntity>) contract.getDeclaredField("entity").get(null);
        return new ContractInfo<>(path, name, supporter, entity, iService);
    }

    /**
     * 通过实现类的实例获取契约信息
     */
    @SneakyThrows
    public static ContractInfo<?, ?> getInfoByBean(Object bean) {
        Class<?> iService = getIService(bean);
        return getInfoByIService(iService);
    }

    /**
     * 通过契约接口获取契约信息
     */
    public static ContractInfo<?, ?> getInfoByIService(Class<?> iService) {
        Class<?> contract = getContract(iService);
        return getInfo(contract, iService);
    }
}
